package com.example.memegenerator.controller;

import com.example.memegenerator.model.dto.MemeDto;
import com.example.memegenerator.service.MemeService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.util.MultiValueMap;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
@RequestMapping("/api/memes")
@RequiredArgsConstructor
public class MemeController {
    private final MemeService memeService;

    @PostMapping
    public ResponseEntity<MemeDto> createMeme(
            @RequestParam("image") MultipartFile image,
            @RequestParam(value = "topText", required = false) String topText,
            @RequestParam(value = "bottomText", required = false) String bottomText) throws Exception {

        MemeDto memeDto = memeService.createMeme(image, topText, bottomText);
        return ResponseEntity.ok(memeDto);
    }

    @GetMapping("/popular")
    public ResponseEntity<Page<MemeDto>> getPopularMemes(Pageable pageable) {
        Page<MemeDto> memes = memeService.getPopularMemes(pageable);
        return ResponseEntity.ok(memes);
    }

    @PostMapping("/{id}/share")
    public ResponseEntity<MemeDto> shareMeme(@PathVariable Long id) {
        MemeDto memeDto = memeService.incrementShareCount(id);
        return ResponseEntity.ok(memeDto);
    }
    
    @PostMapping("/generate-gif")
    public ResponseEntity<byte[]> generateGif(
            @RequestParam("image") MultipartFile image,
            @RequestParam(value = "topText", required = false) String topText,
            @RequestParam(value = "bottomText", required = false) String bottomText,
            @RequestParam(value = "frames", defaultValue = "20") int frames,
            @RequestParam(value = "delay", defaultValue = "100") int delay,
            @RequestParam(value = "animationType", defaultValue = "bounce") String animationType,
            @RequestParam(value = "textCount", defaultValue = "0") int textCount,
            @RequestParam(value = "fontFamily", defaultValue = "Arial") String fontFamily,
            @RequestParam(value = "fontSize", defaultValue = "30") int fontSize,
            @RequestParam(value = "fontColor", defaultValue = "#FFFFFF") String fontColor,
            @RequestParam(value = "strokeColor", defaultValue = "#000000") String strokeColor,
            @RequestParam(value = "strokeWidth", defaultValue = "3") int strokeWidth,
            @RequestParam(value = "bold", defaultValue = "true") boolean bold,
            @RequestParam(value = "italic", defaultValue = "false") boolean italic,
            @RequestParam(value = "textAlign", defaultValue = "center") String textAlign,
            @RequestParam(value = "topTextY", required = false, defaultValue = "0") int topTextY,
            @RequestParam(value = "bottomTextY", required = false, defaultValue = "0") int bottomTextY,
            @RequestParam(required = false) MultiValueMap<String, String> allParams) throws IOException {
        
        // 收集所有文本元素信息
        List<MemeService.TextElement> textElements = new ArrayList<>();
        
        // 处理多文本元素
        if (textCount > 0) {
            for (int i = 0; i < textCount; i++) {
                String text = allParams.getFirst("text" + i);
                if (text != null && !text.isEmpty()) {
                    TextElement element = new TextElement();
                    element.setText(text);
                    
                    // 获取X坐标，如果不存在则使用居中位置
                    String xStr = allParams.getFirst("textX" + i);
                    int x = xStr != null ? Integer.parseInt(xStr) : 0;
                    element.setX(x);
                    
                    // 获取Y坐标
                    String yStr = allParams.getFirst("textY" + i);
                    int y = yStr != null ? Integer.parseInt(yStr) : 0;
                    element.setY(y);
                    
                    // 获取文本样式
                    element.setAlign(allParams.getFirst("textAlign" + i));
                    
                    // 获取字体和大小
                    String fontFamilyValue = allParams.getFirst("fontFamily" + i);
                    element.setFontFamily(fontFamilyValue != null ? fontFamilyValue : fontFamily);
                    
                    String fontSizeValue = allParams.getFirst("fontSize" + i);
                    element.setFontSize(fontSizeValue != null ? Integer.parseInt(fontSizeValue) : fontSize);
                    
                    // 获取颜色信息
                    String fontColorValue = allParams.getFirst("fontColor" + i);
                    element.setFontColor(fontColorValue != null ? fontColorValue : fontColor);
                    
                    String strokeColorValue = allParams.getFirst("strokeColor" + i);
                    element.setStrokeColor(strokeColorValue != null ? strokeColorValue : strokeColor);
                    
                    String strokeWidthValue = allParams.getFirst("strokeWidth" + i);
                    element.setStrokeWidth(strokeWidthValue != null ? Integer.parseInt(strokeWidthValue) : strokeWidth);
                    
                    // 获取样式标志
                    String boldValue = allParams.getFirst("bold" + i);
                    element.setBold(boldValue != null ? Boolean.parseBoolean(boldValue) : bold);
                    
                    String italicValue = allParams.getFirst("italic" + i);
                    element.setItalic(italicValue != null ? Boolean.parseBoolean(italicValue) : italic);
                    
                    // 获取阴影设置
                    String shadowValue = allParams.getFirst("shadow" + i);
                    boolean hasShadow = shadowValue != null ? Boolean.parseBoolean(shadowValue) : false;
                    element.setHasShadow(hasShadow);
                    
                    if (hasShadow) {
                        String shadowColorValue = allParams.getFirst("shadowColor" + i);
                        element.setShadowColor(shadowColorValue != null ? shadowColorValue : "#000000");
                        
                        String shadowBlurValue = allParams.getFirst("shadowBlur" + i);
                        element.setShadowBlur(shadowBlurValue != null ? Integer.parseInt(shadowBlurValue) : 3);
                        
                        String shadowOffsetXValue = allParams.getFirst("shadowOffsetX" + i);
                        element.setShadowOffsetX(shadowOffsetXValue != null ? Integer.parseInt(shadowOffsetXValue) : 2);
                        
                        String shadowOffsetYValue = allParams.getFirst("shadowOffsetY" + i);
                        element.setShadowOffsetY(shadowOffsetYValue != null ? Integer.parseInt(shadowOffsetYValue) : 2);
                    }
                    
                    textElements.add(element);
                }
            }
        }
        
        // 调用服务生成GIF
        byte[] gifData;
        if (!textElements.isEmpty()) {
            // 使用增强的多文本元素方法
            gifData = memeService.generateGifWithMultipleTexts(
                    image, textElements, frames, delay, animationType);
        } else {
            // 回退到原始方法以保持兼容性
            gifData = memeService.generateGif(
                    image, topText, bottomText, frames, delay, animationType,
                    fontFamily, fontSize, fontColor, strokeColor, strokeWidth,
                    bold, italic, textAlign, topTextY, bottomTextY);
        }
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_GIF);
        headers.setContentLength(gifData.length);
        headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=meme.gif");
        
        return new ResponseEntity<>(gifData, headers, HttpStatus.OK);
    }
    
    /**
     * 生成具有多个文本元素的GIF表情包
     * 
     * @param imageFile 基础图片文件
     * @param multiTextElementsJson 包含多个文本元素信息的JSON数据
     * @param frames 帧数
     * @param delay 帧间延迟（毫秒）
     * @param animationType 动画类型
     * @return 生成的GIF图像
     */
    @PostMapping("/generate-multi-text-gif")
    public ResponseEntity<byte[]> generateGifWithMultipleTexts(
            @RequestParam("image") MultipartFile imageFile,
            @RequestParam("textElements") String multiTextElementsJson,
            @RequestParam(value = "frames", defaultValue = "20") int frames,
            @RequestParam(value = "delay", defaultValue = "100") int delay,
            @RequestParam(value = "animationType", defaultValue = "none") String animationType) {
        
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            List<TextElement> controllerTextElements = objectMapper.readValue(
                multiTextElementsJson, 
                objectMapper.getTypeFactory().constructCollectionType(List.class, TextElement.class)
            );
            
            // 将控制器的TextElement对象转换为服务需要的TextElement对象
            List<MemeService.TextElement> serviceTextElements = new ArrayList<>();
            for(TextElement element : controllerTextElements) {
                MemeService.TextElement serviceElement = new MemeService.TextElement();
                serviceElement.setText(element.getText());
                serviceElement.setX(element.getX());
                serviceElement.setY(element.getY());
                serviceElement.setAlign(element.getAlign());
                serviceElement.setFontFamily(element.getFontFamily());
                serviceElement.setFontSize(element.getFontSize());
                serviceElement.setFontColor(element.getFontColor());
                serviceElement.setStrokeColor(element.getStrokeColor());
                serviceElement.setStrokeWidth(element.getStrokeWidth());
                serviceElement.setBold(element.isBold());
                serviceElement.setItalic(element.isItalic());
                serviceElement.setHasShadow(element.isHasShadow());
                serviceElement.setShadowColor(element.getShadowColor());
                serviceElement.setShadowBlur(element.getShadowBlur());
                serviceElement.setShadowOffsetX(element.getShadowOffsetX());
                serviceElement.setShadowOffsetY(element.getShadowOffsetY());
                serviceElement.setAnimation(element.getAnimation());
                serviceTextElements.add(serviceElement);
            }
            
            // 生成GIF图像
            byte[] gifData = memeService.generateGifWithMultipleTexts(
                imageFile, serviceTextElements, frames, delay, animationType);
            
            // 设置响应头，返回GIF数据
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_GIF);
            headers.setContentLength(gifData.length);
            String filename = "meme_" + System.currentTimeMillis() + ".gif";
            headers.setContentDispositionFormData("attachment", filename);
            
            return new ResponseEntity<>(gifData, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    
    // 用于保存文本元素数据的内部类
    private static class TextElement extends MemeService.TextElement {
        private String text;
        private int x;
        private int y;
        private String align;
        private String fontFamily;
        private int fontSize;
        private String fontColor;
        private String strokeColor;
        private int strokeWidth;
        private boolean bold;
        private boolean italic;
        private boolean hasShadow;
        private String shadowColor;
        private int shadowBlur;
        private int shadowOffsetX;
        private int shadowOffsetY;
        private String animation;
        
        // Getters and setters
        
        public String getText() { return text; }
        public void setText(String text) { this.text = text; }
        
        public int getX() { return x; }
        public void setX(int x) { this.x = x; }
        
        public int getY() { return y; }
        public void setY(int y) { this.y = y; }
        
        public String getAlign() { return align; }
        public void setAlign(String align) { this.align = align; }
        
        public String getFontFamily() { return fontFamily; }
        public void setFontFamily(String fontFamily) { this.fontFamily = fontFamily; }
        
        public int getFontSize() { return fontSize; }
        public void setFontSize(int fontSize) { this.fontSize = fontSize; }
        
        public String getFontColor() { return fontColor; }
        public void setFontColor(String fontColor) { this.fontColor = fontColor; }
        
        public String getStrokeColor() { return strokeColor; }
        public void setStrokeColor(String strokeColor) { this.strokeColor = strokeColor; }
        
        public int getStrokeWidth() { return strokeWidth; }
        public void setStrokeWidth(int strokeWidth) { this.strokeWidth = strokeWidth; }
        
        public boolean isBold() { return bold; }
        public void setBold(boolean bold) { this.bold = bold; }
        
        public boolean isItalic() { return italic; }
        public void setItalic(boolean italic) { this.italic = italic; }
        
        public boolean isHasShadow() { return hasShadow; }
        public void setHasShadow(boolean hasShadow) { this.hasShadow = hasShadow; }
        
        public String getShadowColor() { return shadowColor; }
        public void setShadowColor(String shadowColor) { this.shadowColor = shadowColor; }
        
        public int getShadowBlur() { return shadowBlur; }
        public void setShadowBlur(int shadowBlur) { this.shadowBlur = shadowBlur; }
        
        public int getShadowOffsetX() { return shadowOffsetX; }
        public void setShadowOffsetX(int shadowOffsetX) { this.shadowOffsetX = shadowOffsetX; }
        
        public int getShadowOffsetY() { return shadowOffsetY; }
        public void setShadowOffsetY(int shadowOffsetY) { this.shadowOffsetY = shadowOffsetY; }
        
        public String getAnimation() { return animation; }
        public void setAnimation(String animation) { this.animation = animation; }
    }
}